package tax;

import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.such.kit.Callable;
import com.such.kit.Logger;
import com.such.kit.cache.CacheCommons;
import com.such.kit.datacast.CastCommons;
import com.such.kit.file.FileCommons;
import com.such.kit.file.bean.FileInfo;
import com.such.kit.file.support.FileFilter;
import com.such.kit.io.simple.ExcelIOSimple;
import com.such.kit.io.source.MemoryIOSource;
import com.such.kit.io.template.ExcelIOTemplate;
import com.such.kit.string.StringCommons;
import com.such.kit.validate.ValidateCommons;
import com.such.kitx.tax.agent.AgentServer;
import com.such.kitx.tax.impl.baiwang.BaiwangTax;

public class Baiwang {

	private static String address = "http://localhost:8080/ws/test";
	private static SimpleDateFormat sdf = new SimpleDateFormat(CastCommons.DATE_TIME_NUMBER);
	private static String ioCache = CacheCommons.buildCacheName(Baiwang.class, "io");
	private static Callable<MemoryIOSource, List<Map<String, Object>>> simpleInputCaller = new Callable<MemoryIOSource, List<Map<String,Object>>>() {
		public List<Map<String, Object>> call(MemoryIOSource inputSource) throws Exception {
			return inputSource.getInputResult("input");
		}
	};

	private BaiwangTax tax;
	private String reqTPath = "";
	private String resTPath = "";
	private String reqRPath = "";
	private String reqBackupRPath = "";
	private String resRPath = "";

	public Baiwang(String basePath, String interfaceVersion) {
		this.tax = new BaiwangTax(interfaceVersion, address);
		this.reqTPath = FileCommons.appendPathNode(basePath, "template/baiwang/req");
		this.resTPath = FileCommons.appendPathNode(basePath, "template/baiwang/res");
		this.reqRPath = FileCommons.appendPathNode(basePath, "resource/baiwang/req");
		this.reqBackupRPath = FileCommons.appendPathNode(basePath, "resource/baiwang/req/backup");
		this.resRPath = FileCommons.appendPathNode(basePath, "resource/baiwang/res");
	}

	public void start() {
		while(true) {
			run();
		}
	}

	private void run() {
		try {
			Logger.info(getClass(), StringCommons.merger("轮询.开始 [", sdf.format(new Date()), "]"));
			FileCommons.listFolder(this.reqRPath, new FileFilter() {
				public boolean accept(FileInfo fileInfo) {
					String type = fileInfo.getType();
					if (ExcelIOSimple.FILE_TYPE_XLS.equals(type) || ExcelIOSimple.FILE_TYPE_XLSX.equals(type)) {
						return true;
					}
					return false;
				}
			}, new Callable<FileInfo, Void>() {
				public Void call(FileInfo fileInfo) throws Exception {
					String name = fileInfo.getName();
					if (name.startsWith("KJFP")) {
						invoke(fileInfo, new Callable<MemoryIOSource, List<Map<String, Object>>>() {
							public List<Map<String, Object>> call(MemoryIOSource inputSource) throws Exception {
								List<Map<String, Object>> inputs = inputSource.getInputResult("input");
								if (ValidateCommons.isNotEmpty(inputs)) {
									for (Map<String, Object> input : inputs) {
										List<Map<String, Object>> group = inputSource.getInputResult("group_#[LOGIC_ID]", input);
										input.put("fyxm", group);
									}
								}
								return inputs;
							}
						});
					} else if (name.startsWith("DYSZ")) {
						simpleInvoke(fileInfo);
					} else if (name.startsWith("DYFP")) {
						simpleInvoke(fileInfo);
					} else if (name.startsWith("ZFFP")) {
						simpleInvoke(fileInfo);
					} else if (name.startsWith("FPSC")) {
						simpleInvoke(fileInfo);
					} else if (name.startsWith("FPGX")) {
						simpleInvoke(fileInfo);
					} else if (name.startsWith("SCHZ")) {
						invoke(fileInfo, new Callable<MemoryIOSource, List<Map<String, Object>>>() {
							public List<Map<String, Object>> call(MemoryIOSource inputSource) throws Exception {
								List<Map<String, Object>> inputs = inputSource.getInputResult("input");
								if (ValidateCommons.isNotEmpty(inputs)) {
									for (Map<String, Object> input : inputs) {
										List<Map<String, Object>> group = inputSource.getInputResult("group_#[LOGIC_ID]", input);
										input.put("FYXMJJE", group);
									}
								}
								return inputs;
							}
						});
					} else if (name.startsWith("CB")) {
						simpleInvoke(fileInfo);
					} else if (name.startsWith("QK")) {
						simpleInvoke(fileInfo);
					}
					return null;
				}
			});
			Logger.info(getClass(), StringCommons.merger("轮询.结束 [", sdf.format(new Date()), "]"));
		} catch (Exception e) {
			Logger.error(getClass(), "轮询异常", e);
		} finally {
			try {
				Logger.info(getClass(), "休眠 1 分钟，等待下次轮询");
				Thread.sleep(1000 * 60); // 休眠 1 分钟
			} catch (InterruptedException e) {
				Logger.error(getClass(), "休眠异常", e);
			}
		}
	}

	private void simpleInvoke(FileInfo fileInfo) throws Exception {
		invoke(fileInfo, simpleInputCaller);
	}

	private void invoke(FileInfo fileInfo, Callable<MemoryIOSource, List<Map<String, Object>>> inputCaller) throws Exception {
		String name = fileInfo.getName();
		String type = fileInfo.getType();
		String _inputTemplate = null;
		String _outputTemplate = null;
		if (name.startsWith("KJFP")) {
			_inputTemplate = FileCommons.appendPathNode(this.reqTPath, StringCommons.merger("KJFP.", type));
			_outputTemplate = FileCommons.appendPathNode(this.resTPath, StringCommons.merger("KJFP.", type));
		} else if (name.startsWith("DYSZ")) {
			_inputTemplate = FileCommons.appendPathNode(this.reqTPath, StringCommons.merger("DYSZ.", type));
			_outputTemplate = FileCommons.appendPathNode(this.resTPath, StringCommons.merger("DYSZ.", type));
		} else if (name.startsWith("DYFP")) {
			_inputTemplate = FileCommons.appendPathNode(this.reqTPath, StringCommons.merger("DYFP.", type));
			_outputTemplate = FileCommons.appendPathNode(this.resTPath, StringCommons.merger("DYFP.", type));
		} else if (name.startsWith("ZFFP")) {
			_inputTemplate = FileCommons.appendPathNode(this.reqTPath, StringCommons.merger("ZFFP.", type));
			_outputTemplate = FileCommons.appendPathNode(this.resTPath, StringCommons.merger("ZFFP.", type));
		} else if (name.startsWith("FPSC")) {
			_inputTemplate = FileCommons.appendPathNode(this.reqTPath, StringCommons.merger("FPSC.", type));
			_outputTemplate = FileCommons.appendPathNode(this.resTPath, StringCommons.merger("FPSC.", type));
		} else if (name.startsWith("FPGX")) {
			_inputTemplate = FileCommons.appendPathNode(this.reqTPath, StringCommons.merger("FPGX.", type));
			_outputTemplate = FileCommons.appendPathNode(this.resTPath, StringCommons.merger("FPGX.", type));
		} else if (name.startsWith("SCHZ")) {
			_inputTemplate = FileCommons.appendPathNode(this.reqTPath, StringCommons.merger("SCHZ.", type));
			_outputTemplate = FileCommons.appendPathNode(this.resTPath, StringCommons.merger("SCHZ.", type));
		} else if (name.startsWith("CB")) {
			_inputTemplate = FileCommons.appendPathNode(this.reqTPath, StringCommons.merger("CB.", type));
			_outputTemplate = FileCommons.appendPathNode(this.resTPath, StringCommons.merger("CB.", type));
		} else if (name.startsWith("QK")) {
			_inputTemplate = FileCommons.appendPathNode(this.reqTPath, StringCommons.merger("QK.", type));
			_outputTemplate = FileCommons.appendPathNode(this.resTPath, StringCommons.merger("QK.", type));
		}
		final String inputTemplate = _inputTemplate;
		final String outputTemplate = _outputTemplate;
		String inputResource = fileInfo.getPath();
		String outputResource = FileCommons.appendPathNode(this.resRPath, name);

		Logger.info(getClass(), StringCommons.merger("处理文件 [", inputResource, "] 开始"));
		Logger.info(getClass(), StringCommons.merger("使用 InputTemplate [", inputTemplate, "]"));
		Logger.info(getClass(), StringCommons.merger("使用 OutputTemplate [", outputTemplate, "]"));

		ExcelIOTemplate inputIO = CacheCommons.get(ioCache, inputTemplate, new Callable<String, ExcelIOTemplate>() {
			public ExcelIOTemplate call(String cahceName) throws Exception {
				return new ExcelIOTemplate(inputTemplate);
			}
		});
		MemoryIOSource inputSource = new MemoryIOSource();
		inputSource.clearInput();
		inputIO.input(inputSource, inputResource);
		List<Map<String, Object>> paramsList = inputCaller.call(inputSource);
		FileCommons.cutFile(inputResource, FileCommons.appendPathNode(this.reqBackupRPath, StringCommons.merger(sdf.format(new Date()), "_", name)));

		ExcelIOTemplate outputIO = CacheCommons.get(ioCache, outputTemplate, new Callable<String, ExcelIOTemplate>() {
			public ExcelIOTemplate call(String cahceName) throws Exception {
				return new ExcelIOTemplate(outputTemplate);
			}
		});
		MemoryIOSource outputSource = new MemoryIOSource();
		outputSource.clearOutput();
		List<Map<String, Object>> results = null;
		if (name.startsWith("KJFP")) {
			results = this.tax.KJFP(paramsList.toArray(new Map[0]));
		} else if (name.startsWith("DYSZ")) {
			results = this.tax.DYSZ(paramsList.toArray(new Map[0]));
		} else if (name.startsWith("DYFP")) {
			results = this.tax.DYFP(paramsList.toArray(new Map[0]));
		} else if (name.startsWith("ZFFP")) {
			results = this.tax.ZFFP(paramsList.toArray(new Map[0]));
		} else if (name.startsWith("FPSC")) {
			results = this.tax.FPSC(paramsList.toArray(new Map[0]));
		} else if (name.startsWith("FPGX")) {
			results = this.tax.FPGX(paramsList.toArray(new Map[0]));
		} else if (name.startsWith("SCHZ")) {
			results = this.tax.SCHZ(paramsList.toArray(new Map[0]));
		} else if (name.startsWith("CB")) {
			results = this.tax.CB(paramsList.toArray(new Map[0]));
		} else if (name.startsWith("QK")) {
			results = this.tax.QK(paramsList.toArray(new Map[0]));
		}
		if (ValidateCommons.isNotEmpty(results) && ValidateCommons.isNotEmpty(outputSource)) {
			outputSource.setOutputResults("output", null, results);
		}
		outputIO.output(outputSource, new FileOutputStream(outputResource));

		Logger.info(getClass(), StringCommons.merger("处理文件结束，输出反馈文件 [", outputResource, "]"));
	}

	public static void main(String[] args) throws Exception {
		/* 测试参数 
		args = new String[] {
				"D:/SUCH/Works/such/kitx/target/test-classes/tax", 
				"V00000001", 
				"DLL", 
				"D:/SUCH/Works/such/builds/release/tax/lib/jnative/JNativeCpp-1.4-x86.dll", 
				"C:/Program Files (x86)/税控服务器组件接口/NISEC_SKSC.dll", 
				"PostAndRecvEx", 
				"C:/Program Files (x86)/税控服务器组件接口/libeay32.dll", 
				"C:/Program Files (x86)/税控服务器组件接口/ssleay32.dll"
		};
		*/

		int argLen = args.length;
		if (argLen < 6) {
			throw new Exception("缺少关键参数 [应用根目录, 接口版本, 税控服务接口类型, 运行环境库, 需要调用的库, 需要调用的函数]");
		}
		String basePath = args[0];
		String interfaceVersion = args[1];
		String interfaceType = args[2];
		String env = args[3];
		String mainLib = args[4];
		String mainFunc = args[5];
		String[] libs = new String[0];
		if (argLen > 6) {
			libs = Arrays.copyOfRange(args, 6, argLen);
		}
		AgentServer.start(address, interfaceType, env, mainLib, mainFunc, libs);
		new Baiwang(basePath, interfaceVersion).start();
	}

}
